﻿using MQTTnet;
using MQTTnet.Client;
using MQTTnet.Protocol;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Linq.Expressions;
using System.Runtime.InteropServices;
using System.Security.Policy;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using static System.Net.Mime.MediaTypeNames;

namespace WindowsFormsApp
{
    public partial class MainForm : Form
    {
        int crtlSpace;//定义快捷键
        public static IMqttClient _mqttClient;
        public MainForm()
        {
            InitializeComponent();
            crtlSpace = "CtrlSpace".GetHashCode();

            //组合键模式 None = 0,Alt = 1,Ctrl = 2,Shift = 4,WindowsKey = 8
            Win32Api.RegisterHotKey(this.Handle, crtlSpace, 2, (int)Keys.Space);
        }

        /// <summary>
        /// 热键
        /// </summary>
        /// <param name="m"></param>
        protected override void WndProc(ref Message m)
        {
            const int WM_HOTKEY = 0x0312;
            int wParam = (int)m.WParam;
            switch (m.Msg)
            {
                case WM_HOTKEY:
                    if (wParam == crtlSpace)
                    {
                        var text = Clipboard.GetText();
                        string result= YouDao.GetFanYiResult(text);
                        Publish(result);
                        AppentTextLog("触发:【" + text + "】->" + System.DateTime.Now);
                    }
                    break;
            }
            base.WndProc(ref m);
        }

        /// <summary>
        /// 隐藏窗体
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button_closed_Click(object sender, EventArgs e)
        {
            this.Visible = false;
        }

        private void MainForm_Load(object sender, EventArgs e)
        {
            MqttInit();
        }

        /// <summary>
        /// 窗口拖拽
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void MainForm_MouseDown(object sender, MouseEventArgs e)
        {
            Win32Api.ReleaseCapture();
            Win32Api.SendMessage(this.Handle, Win32Api.WM_SYSCOMMAND, Win32Api.SC_MOVE + Win32Api.HTCAPTION, 0);
        }

        /// <summary>
        /// 双击右下角图标显示隐藏
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void notifyIcon1_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                this.Visible = !this.Visible;
            }
        }

        /// <summary>
        /// 右键右下角图标退出程序
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void 退出ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            //卸载注册热键
            Win32Api.UnregisterHotKey(this.Handle, this.crtlSpace);
            //关闭窗口
            this.Close();
        }

        /// <summary>
        /// 初始化MQTT
        /// </summary>
        public void MqttInit()
        {
            string clientId=Guid.NewGuid().ToString();
            var optionsBuilder = new MqttClientOptionsBuilder()
                .WithTcpServer("114.115.132.167", 1883) // 要访问的mqtt服务端的 ip 和 端口号
                                                        //.WithCredentials("admin", "123456") // 要访问的mqtt服务端的用户名和密码
                .WithClientId(clientId) // 设置客户端id
                .WithCleanSession()
                .WithTls(new MqttClientOptionsBuilderTlsParameters
                {
                    UseTls = false  // 是否使用 tls加密
                });

            var clientOptions = optionsBuilder.Build();
            _mqttClient = new MqttFactory().CreateMqttClient();
            _mqttClient.ConnectedAsync += _mqttClient_ConnectedAsync; // 客户端连接成功事件
            _mqttClient.DisconnectedAsync += _mqttClient_DisconnectedAsync; // 客户端连接关闭事件
            _mqttClient.ConnectAsync(clientOptions);
        }

        /// <summary>
        /// 客户端连接关闭事件
        /// </summary>
        /// <param name="arg"></param>
        /// <returns></returns>
        private Task _mqttClient_DisconnectedAsync(MqttClientDisconnectedEventArgs arg)
        {
            AppentTextLog($"MQTT服务已关闭");

            int i = 0;
            Task.Factory.StartNew(() =>
            {
                while (_mqttClient.IsConnected == false)
                {
                    i++;
                    AppentTextLog("尝试重新连..." + i);
                    Thread.Sleep(5 * 1000);
                    _mqttClient.ConnectAsync(_mqttClient.Options);
                    _mqttClient.SubscribeAsync("pc-helper", MqttQualityOfServiceLevel.AtLeastOnce);
                }
            }).ConfigureAwait(false);

            return Task.CompletedTask;
        }

        /// <summary>
        /// 客户端连接成功事件
        /// </summary>
        /// <param name="arg"></param>
        /// <returns></returns>
        private Task _mqttClient_ConnectedAsync(MqttClientConnectedEventArgs arg)
        {
            AppentTextLog($"MQTT服务已连接^v^");

            _mqttClient.SubscribeAsync("pc-helper", MqttQualityOfServiceLevel.AtLeastOnce);

            return Task.CompletedTask;
        }

        /// <summary>
        /// 发送MQTT消息
        /// </summary>
        /// <param name="data"></param>
        public void Publish(string data)
        {
            var message = new MqttApplicationMessage
            {
                Topic = "pc-helper",
                Payload = Encoding.UTF8.GetBytes(data),
                QualityOfServiceLevel = MqttQualityOfServiceLevel.AtLeastOnce,
                Retain = true  // 服务端是否保留消息。true为保留，如果有新的订阅者连接，就会立马收到该消息。
            };
            _mqttClient.PublishAsync(message);
        }

        /// <summary>
        /// 更新窗体文本
        /// </summary>
        /// <param name="text"></param>
        void AppentTextLog(string text)
        {
            Action act = delegate ()
            {
                textBox_log.AppendText(Environment.NewLine + text + Environment.NewLine);
                textBox_log.ScrollToCaret();

                if (textBox_log.Text.Count() > 100000)
                {
                    textBox_log.Clear();
                }
            };
            this.Invoke(act);
        }
    }
}
